﻿using System.Windows;
using System.Collections.Generic;
using System;
using System.Xml.Linq;
using GameEngine.Libs;

namespace GameEngine.Model.Data
{
    public class LevelVO<ThingVOId> : ILevelVO<ThingVOId>
        where ThingVOId : IComparable<ThingVOId>
    {

        //Properties:

        public ILevelVOId Id { get; set; }
        public string Name { get;set;}

        //Containers:

        public List<IWorldVO<ThingVOId>> Worlds { get; set; }

        public LevelVO(ILevelVOId id)
        {
            Id = id;
            Name = "New Level";
            Initialize();
        }

        public LevelVO()
        {
            Initialize();
        }

        void Initialize() {
            Worlds = new List<IWorldVO<ThingVOId>>();            
        }

        public virtual string Serialize()
        {
            //return Serializer.Serialize(VO);
            XDocument doc = new XDocument();
            XElement mainNode = new XElement("LevelVO");
            mainNode.SetAttributeValue("Class", GetType());

            {
                XElement node = new XElement("Id", new XAttribute("Class", Id.GetType()));
                node.Add(Id.Serialize());
                mainNode.Add(node);
            }
            {
                XElement node = new XElement("Name") { Value = Name };
                mainNode.Add(node);
            }
            {
                XElement node = new XElement("Worlds");
                foreach (var row in Worlds)
                {
                    XElement rowXml = new XElement("World", new XAttribute("Class", row.GetType()));
                    rowXml.Add(row.Serialize());
                    node.Add(rowXml);
                }
                mainNode.Add(node);
            }
            return mainNode.ToString();
        }

        public virtual void DeSerialize(string serializedString) {
            XElement mainNode = XElement.Parse(serializedString);
            foreach (XElement node in mainNode.Nodes())
            {
                switch (node.Name.LocalName)
                {
                    case "Name":
                        Name = node.Value;
                        break;
                    case "Id":
                        {
                            var className = node.Attribute("Class").Value;
                            var classType = Type.GetType(className);
                            var instance = Activator.CreateInstance(classType, node.Value) as ILevelVOId;
                            Id = instance;
                        }
                        break;
                    case "Worlds":
                        {
                            foreach (var row in node.Elements()) {
                                var className = row.Attribute("Class").Value;
                                var classType = Type.GetType(className);
                                var instance = Activator.CreateInstance(classType) as IWorldVO<ThingVOId>;
                                instance.DeSerialize(node.Value);
                                Worlds.Add(instance);
                            }
                        }
                        break;
                }
            }
        }
    }

    public class LevelVOId : SimpleId<string>, ILevelVOId{
        public LevelVOId(string id) : base(id) { }
        public LevelVOId() { }
    }
}